#include "tcp_server.h"
#include "up_treaty.h"
#include "app_main.h"
/**
 * @brief 构造函数
 * @param port 监听端口
 * @param onDataReceived 数据接收回调（可选）
 */
SingleClientTcpServer::SingleClientTcpServer(int port, DataCallback onDataReceived)
    : _port(port), _onDataReceived(std::move(onDataReceived)), _running(false), _clientConnected(false), _serverSocket(SocketAddress("0.0.0.0", port)) // 栈上构造，RAII
{
    _serverSocket.setBlocking(false); // 非阻塞监听
    modbus = zlog_get_category(ZLOG_CAG_UP_TY);
    assert(modbus != nullptr);
    zlog_info(modbus, "hello tcp server");
}

SingleClientTcpServer::~SingleClientTcpServer()
{
    // zlog_info(modbus, "exit SingleClientTcpServer");
    stop();
}

/**
 * @brief 启动服务器（在后台线程运行）
 */
void SingleClientTcpServer::start()
{
    if (_running.load())
        return;
    _running = true;
    _workerThread = std::thread(&SingleClientTcpServer::run, this);
}

/**
 * @brief 停止服务器
 */
void SingleClientTcpServer::stop()
{
    // zlog_info(modbus, "stop SingleClientTcpServer");

    if (!_running.exchange(false))
        return; // 如果未运行，直接返回

    if (_workerThread.joinable())
    {
        _workerThread.join(); // 等待线程结束
    }

    // 关闭客户端连接（如果存在）
    {
        if (_clientConnected)
        {
            try
            {
                zlog_info(modbus, " _clientSocket   close");
                _clientSocket.close();
            }
            catch (...)
            {
                zlog_warn(modbus, "exception _clientSocket   close");
            }
            _clientConnected = false;
        }
    }
    // ServerSocket 析构时自动关闭
    cout << "ServerSocket  close" << endl;
}

/**
 * @brief 发送数据
 * @param data 要发送的数据
 * @return 成功发送的字节数，失败返回 -1
 */
int SingleClientTcpServer::sendData(const std::vector<uint8_t> &data)
{
    if (data.empty())
        return 0;

    if (!_clientConnected)
        return -1;

    try
    {
        return _clientSocket.sendBytes(data.data(), static_cast<int>(data.size()));
    }
    catch (const Poco::Exception &ex)
    {
        zlog_warn(modbus, "exception  sendBytes failed: %s", ex.displayText().c_str());
        _clientConnected = false;
        return -1;
    }
    catch (...)
    {
        zlog_warn(modbus, "exception  sendBytes failed: %s", "Unknown error");
        _clientConnected = false;
        return -1;
    }
}

void SingleClientTcpServer::process_event_update(void)
{
    EVENT event;
    std::vector<uint8_t> publish_frame;
    int rsp_num = get_dev_data_ptr()->reg_rsp_num;
    if (get_send_up_queue_ptr()->try_pop(event))
    {
        zlog_info(modbus, "..... RECV AUTO PUSH DATA EVENT: %d", event);
        switch (event)
        {

        case EVENT::RSP_DATA_BASE_STATUS:
            zlog_info(modbus, "publish  data ip=%s port=%d,rsp num = %d", get_app_config_ptr()->cfg.modbus_ip.c_str(), get_app_config_ptr()->cfg.modbus_udp_port, rsp_num);
            // 1.发送状态数据
            get_up_treaty_ptr()->build_rsp_status_data_packet(publish_frame, rsp_num, PUSH_DATA_TYPE::BackgroundStatus);
            hzlog_info(modbus, publish_frame.data(), publish_frame.size());
            sendUdp(get_app_config_ptr()->cfg.modbus_ip, get_app_config_ptr()->cfg.modbus_udp_port, publish_frame.data(), publish_frame.size());
            break;
        case EVENT::RSP_DATA_BASE_ALPHA:
            // 2.发送阿尔法数据
            get_up_treaty_ptr()->build_rsp_result_data_packet(publish_frame, rsp_num, PUSH_DATA_TYPE::BackgroundAlphaValue);
            hzlog_info(modbus, publish_frame.data(), publish_frame.size());
            sendUdp(get_app_config_ptr()->cfg.modbus_ip, get_app_config_ptr()->cfg.modbus_udp_port, publish_frame.data(), publish_frame.size());
            break;
        case EVENT::RSP_DATA_BASE_BETA:
            // 3.发送贝塔数据
            get_up_treaty_ptr()->build_rsp_result_data_packet(publish_frame, rsp_num, PUSH_DATA_TYPE::BackgroundBetaValue);
            hzlog_info(modbus, publish_frame.data(), publish_frame.size());
            sendUdp(get_app_config_ptr()->cfg.modbus_ip, get_app_config_ptr()->cfg.modbus_udp_port, publish_frame.data(), publish_frame.size());
            break;
        case EVENT::RSP_DATA_BASE_GAMA:
            // 4.发送伽马数据
            get_up_treaty_ptr()->build_rsp_result_data_packet(publish_frame, rsp_num, PUSH_DATA_TYPE::BackgroundGammaValue);
            hzlog_info(modbus, publish_frame.data(), publish_frame.size());
            sendUdp(get_app_config_ptr()->cfg.modbus_ip, get_app_config_ptr()->cfg.modbus_udp_port, publish_frame.data(), publish_frame.size());
            break;
        case EVENT::RSP_DATA_BASE_OTHERS:
            // 5.发送其他附加数据
            get_up_treaty_ptr()->build_rsp_others_data_packet(publish_frame, PUSH_DATA_TYPE::MeasurementOthers);
            hzlog_info(modbus, publish_frame.data(), publish_frame.size());
            sendUdp(get_app_config_ptr()->cfg.modbus_ip, get_app_config_ptr()->cfg.modbus_udp_port, publish_frame.data(), publish_frame.size());

            break;
        case EVENT::HEART_BEAT:
            break;
        case EVENT::GET_DEV_CONFIG:
            break;
        default:
            break;
        }
    }
}
/**
 * @brief 设置数据接收回调
 */
void SingleClientTcpServer::setOnDataReceived(DataCallback cb)
{
    assert(cb != nullptr);
    _onDataReceived = std::move(cb);
}

void SingleClientTcpServer::run()
{
    while (_running.load())
    {
        try
        {
            // 非阻塞 accept        30ms
            if (_serverSocket.poll(30000, Poco::Net::Socket::SELECT_READ))
            {
                StreamSocket newClient = _serverSocket.acceptConnection();
                zlog_info(modbus, "new client  %s", newClient.peerAddress().toString().c_str());
                // 关闭旧连接（如果有）
                {

                    if (_clientConnected)
                    {
                        try
                        {
                            zlog_info(modbus, " old _clientSocket    close");
                            _clientSocket.close();
                        }
                        catch (...)
                        {
                            zlog_warn(modbus, "exception _clientSocket   close");
                        }
                    }

                    _clientSocket = std::move(newClient);
                    _clientSocket.setBlocking(false);
                    _clientConnected = true;
                }
            }

            // 处理客户端数据读取
            processClientData();
        }
        catch (const Poco::TimeoutException &)
        {
            // poll 超时，继续循环
        }
        catch (const Poco::Exception &ex)
        {
            zlog_warn(modbus, "exception  poll timeout");
        }
        catch (...)
        {
            zlog_warn(modbus, "exception  unknown error");
        }
        // 处理事件
        process_event_update();
    }
}

void SingleClientTcpServer::processClientData()
{
    std::vector<uint8_t> buffer(1024);

    if (!_clientConnected)
        return;

    try
    {
        int n = _clientSocket.poll(100000, Poco::Net::Socket::SELECT_READ);
        if (n > 0)
        {
            int received = _clientSocket.receiveBytes(buffer.data(), buffer.size());

            if (received > 0)
            {
                buffer.resize(received);
                zlog_info(modbus, "received %d bytes from client", received);
                hzlog_info(modbus, buffer.data(), buffer.size());
                if (_onDataReceived)
                {
                    _onDataReceived(buffer);
                }
            }
            else
            {
                _clientSocket.close();
                _clientConnected = false;
                zlog_warn(modbus, "client disconnected");
            }
        }
    }
    catch (const Poco::TimeoutException &)
    {
    }
    catch (const Poco::Exception &ex)
    {
        zlog_warn(modbus, "client disconnected");
        _clientConnected = false;
    }
    catch (...)
    {
        zlog_warn(modbus, "exception  unknown error");
        _clientConnected = false;
    }
}

/**
 * @brief 发送 UDP 数据包
 *
 * @param ip 目标IP地址（字符串形式）
 * @param port 目标端口
 * @param buffer 数据缓冲区
 * @param length 数据长度（字节）
 * @return int 成功返回发送字节数，失败返回 -1
 */
int sendUdp(const std::string &ip,
            unsigned short port,
            const void *buffer,
            int length)
{
    try
    {
        // 创建 UDP 套接字
        SocketAddress localAddr("0.0.0.0", 54321); // 本地绑定到 54321
        DatagramSocket socket(localAddr);

        // 构造目标地址
        SocketAddress target(ip, port);

        // 发送数据
        int sentBytes = socket.sendTo(static_cast<const char *>(buffer), length, target);

        return sentBytes; // 通常等于 length
    }
    catch (const Poco::Exception &ex)
    {
        std::cerr << "Poco Exception: " << ex.displayText() << std::endl;
        return -1;
    }
    catch (const std::exception &ex)
    {
        std::cerr << "STD Exception: " << ex.what() << std::endl;
        return -1;
    }
    catch (...)
    {
        std::cerr << "Unknown Exception" << std::endl;
        return -1;
    }
}
